<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="FWTfs" id="FWTfs"><span data-lake-id="u13e91ced" id="u13e91ced">典型回答</span></h1>
  <ol list="u2fbd5e43">
   <li fid="u05d9bcbd" data-lake-id="u7bfbe227" id="u7bfbe227"><span data-lake-id="ucbcadc15" id="ucbcadc15">在调用集合前，使用synchronized或者ReentrantLock对代码加锁（读写都要加锁）</span></li>
  </ol>
  <p data-lake-id="u633f30f0" id="u633f30f0"><span data-lake-id="ueb105078" id="ueb105078">​</span><br></p>
  <pre lang="java"><code>
public class SynchronizedCollectionExample {
    private List&lt;Integer&gt; list = new ArrayList&lt;&gt;();

    public void add(int value) {
        synchronized (SynchronizedCollectionExample.class) {
            list.add(value);
        }
    }

    public int get(int index) {
        synchronized (SynchronizedCollectionExample.class) {
            return list.get(index);
        }
    }
}

</code></pre>
  <p data-lake-id="u545a895e" id="u545a895e"><span data-lake-id="u3a49cc6c" id="u3a49cc6c">​</span><br></p>
  <ol list="u2fbd5e43" start="2">
   <li fid="u05d9bcbd" data-lake-id="u939de23a" id="u939de23a"><span data-lake-id="ud9a10406" id="ud9a10406">使用ThreadLocal，将集合放到线程内访问，但是这样集合中的值就不能被其他线程访问了</span></li>
  </ol>
  <p data-lake-id="u8ae77c8d" id="u8ae77c8d"><span data-lake-id="u91450d7c" id="u91450d7c">​</span><br></p>
  <pre lang="java"><code>
public class ThreadLocalCollectionExample {
    private ThreadLocal&lt;List&lt;Integer&gt;&gt; threadLocalList = ThreadLocal.withInitial(ArrayList::new);

    public void add(int value) {
        threadLocalList.get().add(value);
    }

    public int get(int index) {
        return threadLocalList.get().get(index);
    }
}

</code></pre>
  <p data-lake-id="u9fb480c4" id="u9fb480c4"><span data-lake-id="uc84ef612" id="uc84ef612">​</span><br></p>
  <ol list="u2fbd5e43" start="3">
   <li fid="u05d9bcbd" data-lake-id="u9153a737" id="u9153a737"><span data-lake-id="ufe068cc7" id="ufe068cc7">使用Collections.synchronizedXXX()方法，可以获得一个线程安全的集合</span></li>
  </ol>
  <p data-lake-id="uf98d864e" id="uf98d864e"><span data-lake-id="u88b00483" id="u88b00483">​</span><br></p>
  <pre lang="java"><code>
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;

public class CollectionsSynchronizedExample {
    List&lt;Integer&gt; synchronizedList = Collections.synchronizedList(new ArrayList&lt;Integer&gt;());

    public void add(int value) {
        synchronizedList.add(value);  
    }

    public int get(int index) {
        return synchronizedList.get(index); 
    }
}

</code></pre>
  <p data-lake-id="u7d414420" id="u7d414420"><span data-lake-id="u38e3f99d" id="u38e3f99d">​</span><br></p>
  <ol list="u2fbd5e43" start="4">
   <li fid="u05d9bcbd" data-lake-id="u94eb8b7e" id="u94eb8b7e"><span data-lake-id="u6933e6a7" id="u6933e6a7">使用不可变集合进行封装，当集合是不可变的时候，自然是线程安全的</span></li>
  </ol>
  <p data-lake-id="ud5643b5b" id="ud5643b5b"><br></p>
  <pre lang="java"><code>
import com.google.common.collect.ImmutableList;

public class ImmutableCollectionExample {
    private ImmutableList&lt;Integer&gt; immutableList = ImmutableList.of(1, 2, 3);

    public int get(int index) {
        return immutableList.get(index);
    }
}
</code></pre>
  <p data-lake-id="ubc89f53b" id="ubc89f53b"><br></p>
  <p data-lake-id="u7578c3b0" id="u7578c3b0"><span data-lake-id="u33fc0899" id="u33fc0899">或者：</span></p>
  <p data-lake-id="uc604ce1f" id="uc604ce1f"><span data-lake-id="u886f1c6a" id="u886f1c6a">​</span><br></p>
  <pre lang="java"><code>
import java.util.List;

public class ImmutableJava9Example {
    private List&lt;Integer&gt; immutableList = List.of(1, 2, 3);

    public int get(int index) {
        return immutableList.get(index);
    }
}

</code></pre>
  <p data-lake-id="ud9c5c8d5" id="ud9c5c8d5"><br></p>
  <h1 data-lake-id="QT6Pf" id="QT6Pf"><span data-lake-id="u56dbd866" id="u56dbd866">扩展知识</span></h1>
  <h2 data-lake-id="mMGRF" id="mMGRF"><span data-lake-id="u78cd1a5f" id="u78cd1a5f">Java有哪些线程安全的集合？</span></h2>
  <p data-lake-id="uc6304717" id="uc6304717"><span data-lake-id="u0184a9ab" id="u0184a9ab">Java1.5并发包（java.util.concurrent）包含线程安全集合类，允许在迭代时修改集合。</span></p>
  <p data-lake-id="udb5006d4" id="udb5006d4"><span data-lake-id="ufb99f86d" id="ufb99f86d">Java并发集合类主要包含以下几种：</span></p>
  <ol list="u0166ea10">
   <li fid="u611594ec" data-lake-id="u61174c85" id="u61174c85"><span data-lake-id="ucac1d152" id="ucac1d152">ConcurrentHashMap</span></li>
   <li fid="u611594ec" data-lake-id="u62e705ee" id="u62e705ee"><span data-lake-id="uce714042" id="uce714042">ConcurrentLinkedDeque</span></li>
   <li fid="u611594ec" data-lake-id="u5cf44f1d" id="u5cf44f1d"><span data-lake-id="u4a94ebfa" id="u4a94ebfa">ConcurrentLinkedQueue</span></li>
   <li fid="u611594ec" data-lake-id="u0fa6ee4d" id="u0fa6ee4d"><span data-lake-id="ud4f07ddf" id="ud4f07ddf">ConcurrentSkipListMap</span></li>
   <li fid="u611594ec" data-lake-id="uc991f3e5" id="uc991f3e5"><span data-lake-id="u4f24d7fa" id="u4f24d7fa">ConcurrentSkipSet</span></li>
   <li fid="u611594ec" data-lake-id="u8790b4f4" id="u8790b4f4"><span data-lake-id="u636a9744" id="u636a9744">CopyOnWriteArrayList</span></li>
   <li fid="u611594ec" data-lake-id="ubd83fc2a" id="ubd83fc2a"><span data-lake-id="uf2c0d870" id="uf2c0d870">CopyOnWriteArraySet</span></li>
  </ol>
  <h2 data-lake-id="hD3y1" id="hD3y1"><span data-lake-id="u351443ff" id="u351443ff">什么是写时复制？</span></h2>
 </body>
</html>